#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <time.h>

using namespace std;

#define BASE_ID_GIVEN 1
#define INIT 1
#define HANDO 1
#define TERMI -1
#define DEADE -3 //dead end

#define SAMPLENO 100
#define BLOCKSIZE 1024
#define BASENO 20
#define SMEMSIZE	BLOCKSIZE*(sizeof(int)+sizeof(int))
#define GSIZE(elemNo) \
	elemNo%BLOCKSIZE==0?elemNo/BLOCKSIZE:elemNo/BLOCKSIZE+1;

#define TRUE 1
#define FALSE 0

#define VERSION 1

typedef struct host_arrays
{
	/*event attributes*/
	int *etype;
	float *duration;
	float *speed;
	float *pos;
	/*event list*/
	float *time;
	int *baseId;
	int *no;
	/*event init required*/
	int *init;
} ha_t;

typedef struct device_arrays{
	/*event attributes*/
	int *etype;		//^_^
	int *sum;		//^_^
	float *duration;
	float *speed;
	float *pos;
	/*event list*/
	int *index;		//^_^
	int *baseId;	//^_^
	int *no;		//^_^
	float *time;
	/*event init required*/
	int *init;
	int *detect;	//^_^
} da_t;

#define timer_start(start, stop) \
	cudaEventCreate(&start);\
	cudaEventCreate(&stop);\
	cudaEventRecord(start, 0);
#define timer_stop(start, stop) \
	float elapsedTime = -1; \
	cudaEventRecord(stop, 0);\
	cudaEventSynchronize(stop);\
	cudaEventElapsedTime(&elapsedTime, start, stop);\
	cudaEventDestroy(start);\
	cudaEventDestroy(stop);\
	cout<<elapsedTime<<"ms"<<endl;

#define printinfo(kernel_name) {\
	std::fstream out1; \
	out1.open(kernel_name, std::ios::out | std::ios::app); \
	int *hdata = (int*)malloc(n*sizeof(int)); \
	int *hflag = (int*)malloc(n*sizeof(int)); \
	int *hindex = (int*)malloc(n*sizeof(int)); \
	int *hno = (int*)malloc(n*sizeof(int)); \
	int *hetype = (int*)malloc(n*sizeof(int)); \
	float *htime = (float*)malloc(n*sizeof(float)); \
	cudaMemcpy(hdata, da.sum, n*sizeof(int), cudaMemcpyDeviceToHost); \
	cudaMemcpy(hflag, da.baseId, n*sizeof(int), cudaMemcpyDeviceToHost); \
	cudaMemcpy(hindex, da.index, n*sizeof(int), cudaMemcpyDeviceToHost); \
	cudaMemcpy(hno, da.no, n*sizeof(int), cudaMemcpyDeviceToHost); \
	cudaMemcpy(hetype, da.etype, n*sizeof(int), cudaMemcpyDeviceToHost); \
	cudaMemcpy(htime, da.time, n*sizeof(float), cudaMemcpyDeviceToHost); \
	out1<<kernel_name<<endl; \
	for(int i=0; i<n; i++){ \
	/*if( hetype[hindex[i]] != -1 && ( hno[hindex[i]] < 0 || hdata[hindex[i]] > 10 ) )*/ \
	if(hno[hindex[i]]<0) \
	out1 \
	<<i<<" " \
	<<hflag[i]<<" " \
	<<hno[hindex[i]]<<" " \
	<<hdata[hindex[i]]<<" " \
	<<hetype[hindex[i]]<<" " \
	<<htime[i]<<endl; \
	out1.flush(); \
	} \
	out1<<endl; \
	out1.close();}

#define printinfoseq(filename) {\
	std::fstream out2; \
	out2.open(filename, std::ios::out | std::ios::app); \
	int *hdata = (int*)malloc(n*sizeof(int)); \
	int *hflag = (int*)malloc(n*sizeof(int)); \
	int *hno = (int*)malloc(n*sizeof(int)); \
	int *hetype = (int*)malloc(n*sizeof(int)); \
	cudaMemcpy(hdata, da.sum, n*sizeof(int), cudaMemcpyDeviceToHost); \
	cudaMemcpy(hflag, da.baseId, n*sizeof(int), cudaMemcpyDeviceToHost); \
	cudaMemcpy(hno, da.no, n*sizeof(int), cudaMemcpyDeviceToHost); \
	cudaMemcpy(hetype, da.etype, n*sizeof(int), cudaMemcpyDeviceToHost); \
	for(int i=0; i<n; i++){ \
	out2 \
	<<i<<" " \
	<<hflag[i]<<" " \
	<<hno[i]<<" " \
	<<hdata[i]<<" " \
	<<hetype[i]<<endl; \
	out2.flush(); \
	} \
	out2<<endl; \
	out2.close();}

#define printinfofini(filename, n) {\
	std::fstream out; \
	out.open(filename, std::ios::out); \
	int *hdata = (int*)malloc(n*sizeof(int)); \
	int *hflag = (int*)malloc(n*sizeof(int)); \
	int *hindex = (int*)malloc(n*sizeof(int)); \
	int *hno = (int*)malloc(n*sizeof(int)); \
	int *hetype = (int*)malloc(n*sizeof(int)); \
	float *htime = (float*)malloc(n*sizeof(float)); \
	cudaMemcpy(hdata, da.sum, n*sizeof(int), cudaMemcpyDeviceToHost); \
	cudaMemcpy(hflag, da.baseId, n*sizeof(int), cudaMemcpyDeviceToHost); \
	cudaMemcpy(hindex, da.index, n*sizeof(int), cudaMemcpyDeviceToHost); \
	cudaMemcpy(hno, da.no, n*sizeof(int), cudaMemcpyDeviceToHost); \
	cudaMemcpy(hetype, da.etype, n*sizeof(int), cudaMemcpyDeviceToHost); \
	cudaMemcpy(htime, da.time, n*sizeof(float), cudaMemcpyDeviceToHost); \
	for(int i=0; i<n; i++){ \
	/*if(hno[hindex[i]]<0)*/ \
	out \
	<<hindex[i]<<" " \
	<<hflag[i]<<" " \
	<<hno[hindex[i]]<<" " \
	<<hdata[hindex[i]]<<" " \
	<<hetype[hindex[i]]<<" " \
	<<htime[i]<<endl; \
	out.flush(); \
	} \
	out<<endl; \
	out.close();}